#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
二进制文件生成工具
处理可执行文件、静态库、动态库等二进制目标的创建
"""

import os
import logging
from target_registry import TargetType, BuildTarget

def generate(env):
    """
    生成二进制文件生成工具

    Args:
        env: SCons环境
    """
    _setup_binary_functions(env)

def exists(env):
    """
    检查工具是否存在

    Args:
        env: SCons环境

    Returns:
        True
    """
    return True

def _setup_binary_functions(env):
    """
    设置二进制文件生成相关的函数到SCons环境中

    Args:
        env: SCons环境
    """

    def add_executable(env, name, sources, **kwargs):
        """
        添加可执行文件目标

        Args:
            name: 目标名称
            sources: 源文件列表
            **kwargs: 其他选项
        """
        logging.info(f"AddExecutable called for {name} with kwargs: {kwargs}")
        module_dir = env.get('MODULE_DIR', '.')
        target = BuildTarget(name, TargetType.EXECUTABLE, sources, module_dir)
        _apply_target_options(env, target, **kwargs)
        env._target_registry.register_target(target)
        return target

    def add_static_library(env, name, sources, **kwargs):
        """
        添加静态库目标

        Args:
            name: 目标名称
            sources: 源文件列表
            **kwargs: 其他选项
        """
        module_dir = env.get('MODULE_DIR', '.')
        target = BuildTarget(name, TargetType.STATIC_LIBRARY, sources, module_dir)
        _apply_target_options(env, target, **kwargs)
        env._target_registry.register_target(target)
        return target

    def add_shared_library(env, name, sources, **kwargs):
        """
        添加动态库目标

        Args:
            name: 目标名称
            sources: 源文件列表
            **kwargs: 其他选项
        """
        module_dir = env.get('MODULE_DIR', '.')
        target = BuildTarget(name, TargetType.SHARED_LIBRARY, sources, module_dir)
        _apply_target_options(env, target, **kwargs)
        env._target_registry.register_target(target)
        return target

    def add_object_files(env, name, sources, **kwargs):
        """
        添加目标文件

        Args:
            name: 目标名称
            sources: 源文件列表
            **kwargs: 其他选项
        """
        module_dir = env.get('MODULE_DIR', '.')
        target = BuildTarget(name, TargetType.OBJECT_FILES, sources, module_dir)
        _apply_target_options(env, target, **kwargs)
        env._target_registry.register_target(target)
        return target

    def add_prebuilt_static_library(env, name, library_path, **kwargs):
        """
        添加预编译静态库目标

        Args:
            name: 目标名称
            library_path: 预编译库文件路径
            **kwargs: 其他选项（如export_include_paths等）
        """
        module_dir = env.get('MODULE_DIR', '.')
        # 预编译库没有源文件
        target = BuildTarget(name, TargetType.PREBUILT_STATIC_LIBRARY, [], module_dir)

        # 设置库文件路径
        if os.path.isabs(library_path):
            target.library_path = library_path
        else:
            target.library_path = os.path.join(module_dir, library_path)

        _apply_target_options(env, target, **kwargs)
        env._target_registry.register_target(target)
        return target

    def add_prebuilt_shared_library(env, name, library_path, **kwargs):
        """
        添加预编译动态库目标

        Args:
            name: 目标名称
            library_path: 预编译库文件路径
            **kwargs: 其他选项（如export_include_paths等）
        """
        module_dir = env.get('MODULE_DIR', '.')
        # 预编译库没有源文件
        target = BuildTarget(name, TargetType.PREBUILT_SHARED_LIBRARY, [], module_dir)

        # 设置库文件路径
        if os.path.isabs(library_path):
            target.library_path = library_path
        else:
            target.library_path = os.path.join(module_dir, library_path)

        _apply_target_options(env, target, **kwargs)
        env._target_registry.register_target(target)
        return target

    def add_header_library(env, name, **kwargs):
        """
        添加头文件库目标

        Args:
            name: 目标名称
            **kwargs: 其他选项（如export_include_paths等）
        """
        module_dir = env.get('MODULE_DIR', '.')
        # 头文件库没有源文件
        target = BuildTarget(name, TargetType.HEADER_LIBRARY, [], module_dir)

        _apply_target_options(env, target, **kwargs)
        env._target_registry.register_target(target)
        return target

    def add_proto_library(env, name, proto_files, **kwargs):
        """
        添加Protocol Buffers库目标

        Args:
            name: 目标名称
            proto_files: proto文件列表
            **kwargs: 其他选项
                proto_type: proto类型 (full/lite/min)，默认为full
                proto_path: proto文件搜索路径
                export_include_paths: 导出的头文件路径
        """
        logging.info(f"AddProtoLibrary called for {name} with proto_files: {proto_files}, kwargs: {kwargs}")
        module_dir = env.get('MODULE_DIR', '.')
        target = BuildTarget(name, TargetType.PROTO_LIBRARY, proto_files, module_dir)

        _apply_target_options(env, target, **kwargs)
        env._target_registry.register_target(target)
        logging.info(f"Proto library {name} registered successfully")
        return target

    def _apply_target_options(env, target, **kwargs):
        """
        应用目标选项

        Args:
            env: SCons环境
            target: 编译目标
            **kwargs: 选项字典
        """
        module_dir = env.get('MODULE_DIR', '.')

        # 处理源文件路径
        processed_sources = []
        for source in target.sources:
            if os.path.isabs(source):
                processed_sources.append(source)
            else:
                processed_sources.append(os.path.join(module_dir, source))
        target.sources = processed_sources

        # 依赖项
        if 'depends' in kwargs:
            depends = kwargs['depends']
            if isinstance(depends, str):
                target.add_dependency(depends)
            elif isinstance(depends, list):
                for dep in depends:
                    target.add_dependency(dep)



        # 静态库依赖
        if 'static_libs' in kwargs:
            static_libs = kwargs['static_libs']
            if isinstance(static_libs, str):
                target.add_static_lib(static_libs)
            elif isinstance(static_libs, list):
                for lib in static_libs:
                    target.add_static_lib(lib)

        # 动态库依赖
        if 'shared_libs' in kwargs:
            shared_libs = kwargs['shared_libs']
            if isinstance(shared_libs, str):
                target.add_shared_lib(shared_libs)
            elif isinstance(shared_libs, list):
                for lib in shared_libs:
                    target.add_shared_lib(lib)

        # 头文件库依赖
        if 'header_libs' in kwargs:
            header_libs = kwargs['header_libs']
            logging.info(f"Adding header_libs dependencies for {target.name}: {header_libs}")
            if isinstance(header_libs, str):
                target.add_dependency(header_libs)
                logging.info(f"Added header lib dependency: {header_libs}")
            elif isinstance(header_libs, list):
                for lib in header_libs:
                    target.add_dependency(lib)
                    logging.info(f"Added header lib dependency: {lib}")
        else:
            logging.info(f"No header_libs found for target {target.name}")

        # 库搜索路径
        if 'lib_paths' in kwargs:
            lib_paths = kwargs['lib_paths']
            if isinstance(lib_paths, str):
                target.add_lib_path(_resolve_path(module_dir, lib_paths))
            elif isinstance(lib_paths, list):
                for path in lib_paths:
                    target.add_lib_path(_resolve_path(module_dir, path))

        # 头文件搜索路径
        if 'include_paths' in kwargs:
            include_paths = kwargs['include_paths']
            if isinstance(include_paths, str):
                target.add_include_path(_resolve_path(module_dir, include_paths))
            elif isinstance(include_paths, list):
                for path in include_paths:
                    target.add_include_path(_resolve_path(module_dir, path))

        # 导出的头文件搜索路径
        if 'export_include_paths' in kwargs:
            export_include_paths = kwargs['export_include_paths']
            if isinstance(export_include_paths, str):
                target.add_export_include_path(_resolve_path(module_dir, export_include_paths))
            elif isinstance(export_include_paths, list):
                for path in export_include_paths:
                    target.add_export_include_path(_resolve_path(module_dir, path))

        # 预处理宏定义
        if 'defines' in kwargs:
            defines = kwargs['defines']
            if isinstance(defines, str):
                target.add_define(defines)
            elif isinstance(defines, list):
                for define in defines:
                    target.add_define(define)

        # 编译选项
        if 'cflags' in kwargs:
            target.cflags.extend(_ensure_list(kwargs['cflags']))

        if 'cxxflags' in kwargs:
            target.cxxflags.extend(_ensure_list(kwargs['cxxflags']))

        if 'ldflags' in kwargs:
            target.ldflags.extend(_ensure_list(kwargs['ldflags']))

        # 输出目录
        if 'output_dir' in kwargs:
            target.output_dir = _resolve_path(module_dir, kwargs['output_dir'])

        # 安装目录
        if 'install_dir' in kwargs:
            target.install_dir = _resolve_path(module_dir, kwargs['install_dir'])

        # 处理Proto相关选项
        if target.target_type == TargetType.PROTO_LIBRARY:
            # 处理proto文件列表
            proto_files = kwargs.get('proto_files', target.sources)
            if proto_files:
                target.proto_files = [_resolve_path(module_dir, f) for f in _ensure_list(proto_files)]

            # 处理proto类型
            proto_type = kwargs.get('proto_type', 'full')
            if proto_type in ['full', 'lite', 'min']:
                target.proto_type = proto_type
            else:
                logging.warning(f"Invalid proto_type '{proto_type}', using 'full'")
                target.proto_type = 'full'

            # 处理proto搜索路径
            proto_path = kwargs.get('proto_path')
            if proto_path:
                if isinstance(proto_path, list):
                    # 如果是列表，取第一个路径作为主要搜索路径
                    target.proto_path = _resolve_path(module_dir, proto_path[0]) if proto_path else module_dir
                else:
                    target.proto_path = _resolve_path(module_dir, proto_path)
            else:
                # 默认使用Module目录作为proto搜索路径
                target.proto_path = module_dir

    def _resolve_path(module_dir, path):
        """
        解析路径

        Args:
            module_dir: Module目录
            path: 路径字符串

        Returns:
            解析后的绝对路径
        """
        if os.path.isabs(path):
            return path
        else:
            return os.path.join(module_dir, path)

    def _ensure_list(value):
        """
        确保值为列表

        Args:
            value: 字符串或列表

        Returns:
            列表
        """
        if isinstance(value, str):
            return [value]
        elif isinstance(value, list):
            return value
        else:
            return []

    # 将方法添加到环境中
    env.AddMethod(add_executable, 'AddExecutable')
    env.AddMethod(add_static_library, 'AddStaticLibrary')
    env.AddMethod(add_shared_library, 'AddSharedLibrary')
    env.AddMethod(add_object_files, 'AddObjectFiles')
    env.AddMethod(add_prebuilt_static_library, 'AddPrebuiltStaticLibrary')
    env.AddMethod(add_prebuilt_shared_library, 'AddPrebuiltSharedLibrary')
    env.AddMethod(add_header_library, 'AddHeaderLibrary')
    env.AddMethod(add_proto_library, 'AddProtoLibrary')